//@author A0083782W
#include "IndexTranslator.h"

void MAPPING_UNIT::reset() {
	storageIndex = 0;
	displayIndex = 0;
}

MAPPING_UNIT::MAPPING_UNIT() {
	reset();	
}

void IndexTranslator::update (pos_int deletedIndex) {
	for (pos_int i = deletedIndex + 1; i < _myMappingData.size(); i++ ) {
		_myMappingData[i].storageIndex--;
	}
}

void IndexTranslator::sort () {
	bool sorted = false;
	pos_int i = 0;
	while (sorted == false) {
		sorted = true;
		for (pos_int j = i + 1; j < _myMappingData.size(); j++ ) {
			if (_myMappingData[i].storageIndex > _myMappingData[j].storageIndex) {
				MAPPING_UNIT tempUnit;
				tempUnit = _myMappingData[i];
				_myMappingData[i] = _myMappingData[j];
				_myMappingData[j] = tempUnit;
				sorted = false;
			}
		}
		i++;
	}
}

bool IndexTranslator::isRepeatation() {
	pos_int temp = 0;

	if (_myMappingData.size() != 0) {
		temp = _myMappingData[0].storageIndex;
	}
	for (pos_int i = 1; i < _myMappingData.size(); i++) {
		if (_myMappingData[i].storageIndex != temp) {
			temp = _myMappingData[i].storageIndex;
		}
		else {
			return true;
		}
	}
	return false;
}

void IndexTranslator::reset() {
	_myMappingData.clear();
	_myMappingData.shrink_to_fit();
	_illegalInput = false;
}

IndexTranslator::IndexTranslator() {
	reset();
}

IndexTranslator::IndexTranslator(const vector<pos_int>& displayedIndices) {
	setMapping(displayedIndices);
}

void IndexTranslator::setMapping (const vector<pos_int>& displayedIndices) {
	reset();
	for (pos_int i = 1; i <= displayedIndices.size(); i++) {
		MAPPING_UNIT newUnit;
		newUnit.displayIndex = i;
		newUnit.storageIndex = displayedIndices[i - 1];
		_myMappingData.push_back (newUnit);
	}
	sort();
	if (isRepeatation()) {
		failProgram (ERR_IndexTranslator::repeatitive_array);
	}
}

bool IndexTranslator::deleteMapping (pos_int displayedIndex) {
	for (pos_int i = 0; i < _myMappingData.size(); i++) {
		if (displayedIndex == _myMappingData[i].displayIndex ) {
			update (i);
			_myMappingData.erase (_myMappingData.begin() + i);
			return true;
		}
	}
	return false;
}

bool IndexTranslator::isExecutable() const{
	return !_illegalInput;
}

int IndexTranslator::getStorageIndex (const pos_int displayedIndex) const {
	for (pos_int i = 0; i < _myMappingData.size(); i++) {
		if (displayedIndex == _myMappingData[i].displayIndex ) {
			return _myMappingData[i].storageIndex;
		}
	}
	return -1;
}